package com.mindskip.xzs.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mindskip.xzs.context.WebContext;
import com.mindskip.xzs.domain.dto.ExamPaperQuestionItemObject;
import com.mindskip.xzs.domain.dto.ExamPaperTitleItemObject;
import com.mindskip.xzs.domain.dto.admin.exampaper.*;
import com.mindskip.xzs.domain.entity.ExamPaper;
import com.mindskip.xzs.domain.entity.Question;
import com.mindskip.xzs.domain.entity.TextContent;
import com.mindskip.xzs.domain.enums.ExamPaperTypeEnum;
import com.mindskip.xzs.domain.vo.admin.exampaper.ExamPaperTitleItemVO;
import com.mindskip.xzs.domain.vo.admin.exampaper.ExamPaperVO;
import com.mindskip.xzs.domain.vo.admin.exampaper.ExamPaperWithQuestionVO;
import com.mindskip.xzs.domain.vo.admin.question.QuestionSelectVO;
import com.mindskip.xzs.domain.vo.student.dashboard.FixedPaper;
import com.mindskip.xzs.domain.vo.student.dashboard.PaperFilter;
import com.mindskip.xzs.domain.vo.student.dashboard.TimeLimitPaper;
import com.mindskip.xzs.domain.vo.student.exampaper.ExamPaperPageVO;
import com.mindskip.xzs.repository.BaseMapper;
import com.mindskip.xzs.repository.ExamPaperMapper;
import com.mindskip.xzs.service.ExamPaperService;
import com.mindskip.xzs.service.QuestionService;
import com.mindskip.xzs.service.TextContentService;
import com.mindskip.xzs.utility.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class ExamPaperServiceImpl extends BaseServiceImpl<ExamPaper> implements ExamPaperService {

    private final ExamPaperMapper examPaperMapper;

    private final TextContentService textContentService;

    private final QuestionService questionService;

    private final WebContext webContext;

    public ExamPaperServiceImpl(BaseMapper<ExamPaper> baseMapper, ExamPaperMapper examPaperMapper, TextContentService textContentService, QuestionService questionService, WebContext webContext) {
        super(baseMapper);
        this.examPaperMapper = examPaperMapper;
        this.textContentService = textContentService;
        this.questionService = questionService;
        this.webContext = webContext;
    }

    // 查询所有试卷总数
    @Override
    public Integer selectAllCount() {
        return examPaperMapper.selectAllCount();
    }

    @Override
    public PageInfo<ExamPaperVO> getExamPaperByPage(ExamPaperPageDTO examPaperPageDTO) {

        PageHelper.startPage(examPaperPageDTO.getPageIndex(), examPaperPageDTO.getPageSize(), "id desc");
        List<ExamPaper> examPaperList = examPaperMapper.selectByPage(examPaperPageDTO);
        PageInfo<ExamPaper> oldPageInfo = new PageInfo<>(examPaperList);

        // 将List<ExamPaper>转换为List<ExamPaperVO>
        List<ExamPaperVO> examPaperVOList = examPaperList
                .stream()
                .map(new Function<ExamPaper, ExamPaperVO>() {
                    @Override
                    public ExamPaperVO apply(ExamPaper examPaper) {
                        ExamPaperVO examPaperVO = BeanCopyUtils.copyBean(examPaper, ExamPaperVO.class);
                        // BeanUtils 无法将 Date 类型的属性转换为 String 类型，所以需要手动转换
                        examPaperVO.setCreateTime(DateTimeUtil.dateFormat(examPaper.getCreateTime()));
                        return examPaperVO;
                    }
                })
                .collect(Collectors.toList());

        // 将 oldPageInfo 中的所有属性赋值到 PageInfo<ExamPaperVO> 对象，并更改该对象的List属性为 examPaperVOList
        return PageInfoUtil.copyMap(oldPageInfo, examPaperVOList);
    }

    @Override
    public ExamPaperWithQuestionVO getExamPaperWithQuestion(Integer id) {

        ExamPaper examPaper = examPaperMapper.selectByPrimaryKey(id);
        if (ObjectUtils.isEmpty(examPaper)) {
            throw new RuntimeException("id错误");
        }

        ExamPaperWithQuestionVO examPaperWithQuestionVO = BeanCopyUtils.copyBean(examPaper, ExamPaperWithQuestionVO.class);

        // 给 examPaperWithQuestionVO 的 level 属性赋值
        examPaperWithQuestionVO.setLevel(examPaper.getGradeLevel());

        // 给 examPaperWithQuestionVO 的 score 属性赋值
        examPaperWithQuestionVO.setScore(ExamUtil.scoreToString(examPaper.getScore()));

        // 如果试卷是时段考试类型，则给 limitDateTime 属性设值
        if (ExamPaperTypeEnum.fromCode(examPaper.getPaperType()) == ExamPaperTypeEnum.TimeLimit) {
            List<String> limitDateTime = Arrays.asList(DateTimeUtil.dateFormat(examPaper.getLimitStartTime()),
                    DateTimeUtil.dateFormat(examPaper.getLimitEndTime()));
            // 给 examPaperWithQuestionVO 的 limitDateTime 属性赋值
            examPaperWithQuestionVO.setLimitDateTime(limitDateTime);
        }

        // 给 examPaperWithQuestionVO 的 titleItems 属性赋值
        TextContent textContent = textContentService.selectById(examPaper.getFrameTextContentId());
        List<ExamPaperTitleItemVO> examPaperTitleItemVOList = JsonUtil.toJsonListObject(textContent.getContent(), ExamPaperTitleItemVO.class);
        if (ObjectUtils.isEmpty(examPaperTitleItemVOList)) {
            throw new RuntimeException("文本内容为空");
        }
        List<ExamPaperTitleItemVO> newExamPaperTitleItemVOList = examPaperTitleItemVOList
                .stream()
                .peek(examPaperTitleItemVO -> {
                    List<QuestionSelectVO> list = examPaperTitleItemVO.getQuestionItems()
                            .stream()
                            .map(questionSelectVO -> {
                                Question question = questionService.selectById(questionSelectVO.getId());
                                QuestionSelectVO questionSelectVO1 = questionService.questionToQuestionSelectVO(question);
                                questionSelectVO1.setItemOrder(questionSelectVO.getItemOrder());
                                return questionSelectVO1;
                            })
                            .collect(Collectors.toList());
                    examPaperTitleItemVO.setQuestionItems(list);
                })
                .collect(Collectors.toList());
        examPaperWithQuestionVO.setTitleItems(newExamPaperTitleItemVOList);

        return examPaperWithQuestionVO;
    }

    @Override
    @Transactional
    public ExamPaper insertOrUpdateExamPaper(ExamPaperWithQuestionDTO examPaperWithQuestionDTO) {

        if (examPaperWithQuestionDTO.getId() == null) {
            return insert(examPaperWithQuestionDTO, webContext.getCurrentUser().getId());

        }else {
            return update(examPaperWithQuestionDTO);
        }
    }

    public ExamPaper insert(ExamPaperWithQuestionDTO examPaperWithQuestionDTO, Integer userId) {

        ExamPaper examPaper = new ExamPaper();

        setExamPaperWithQuestionDTOToExamPaper(examPaperWithQuestionDTO, examPaper);

        Date now = new Date();

        // 给 ExamPaper 所对应的 t_text_content 表中的内容插入
        TextContent textContent = new TextContent();

        // 给 textContent 的 createTime 属性赋值
        textContent.setCreateTime(now);

        // 将 ExamPaperWithQuestionDTO 中的 titleItems 属性 转换为 JSON 字符串
        String content = setExamPaperTextContent(examPaperWithQuestionDTO);
        // 给 textContent 的 content 属性赋值
        textContent.setContent(content);

        int i = textContentService.insertByFilter(textContent);
        if (i <= 0) {
            throw new RuntimeException("插入文本内容失败");
        }

        // 给 examPaper 的 frameTextContentId 属性赋值
        examPaper.setFrameTextContentId(textContent.getId());
        // 给 examPaper 的 createUser 属性赋值
        examPaper.setCreateUser(userId);
        // 给 examPaper 的 createTime 属性赋值
        examPaper.setCreateTime(now);
        // 给 examPaper 的 deleted 属性赋值
        examPaper.setDeleted(false);

        int i1 = examPaperMapper.insertSelective(examPaper);
        if (i1 <= 0) {
            throw new RuntimeException("插入试卷失败");
        }

        return examPaper;
    }

    public ExamPaper update(ExamPaperWithQuestionDTO examPaperWithQuestionDTO) {

        ExamPaper examPaper = examPaperMapper.selectByPrimaryKey(examPaperWithQuestionDTO.getId());

        // 将 ExamPaperWithQuestionDTO 转换为 ExamPaper
        setExamPaperWithQuestionDTOToExamPaper(examPaperWithQuestionDTO, examPaper);

        TextContent textContent = textContentService.selectById(examPaper.getFrameTextContentId());

        if (ObjectUtils.isEmpty(textContent)) {
            throw new RuntimeException("查询不到该试卷所对应的文本内容");
        }

        // 将 ExamPaperWithQuestionDTO 中的 titleItems 属性 转换为 JSON 字符串
        String content = setExamPaperTextContent(examPaperWithQuestionDTO);
        textContent.setContent(content);

        int i = textContentService.updateByIdFilter(textContent);
        if (i <= 0) {
            throw new RuntimeException("更新文本内容失败");
        }

        int i1 = examPaperMapper.updateByPrimaryKey(examPaper);
        if (i1 <= 0) {
            throw new RuntimeException("更新试卷失败");
        }

        return examPaper;
    }

    // 将 ExamPaperWithQuestionDTO 转换为 ExamPaper
    public void setExamPaperWithQuestionDTOToExamPaper(ExamPaperWithQuestionDTO examPaperWithQuestionDTO, ExamPaper examPaper) {

        // 给 examPaper 的 id(插入操作时id为null)、name、subjectId、paperType 属性赋值
        BeanUtils.copyProperties(examPaperWithQuestionDTO, examPaper);

        // 给 examPaper 的 gradeLevel 属性赋值
        examPaper.setGradeLevel(examPaperWithQuestionDTO.getLevel());

        int count = 0;
        List<ExamPaperTitleItemDTO> titleItems = examPaperWithQuestionDTO.getTitleItems();
        for (ExamPaperTitleItemDTO examPaperTitleItemDTO : titleItems) {
            int size = examPaperTitleItemDTO.getQuestionItems().size();
            count += size;
        }
        // 给 examPaper 的 questionCount 属性赋值
        examPaper.setQuestionCount(count);

        int score = examPaperWithQuestionDTO.getTitleItems().stream().
                flatMapToInt(t -> t.getQuestionItems()
                        .stream()
                        .mapToInt(q -> ExamUtil.scoreToInteger(q.getScore()))
                ).sum();
        // 给 examPaper 的 score 属性赋值
        examPaper.setScore(score);

        // 如果试卷类型是时段考试，则要给 examPaper 的 limitStartTime、 limitEndTime 属性赋值
        if (ExamPaperTypeEnum.TimeLimit == ExamPaperTypeEnum.fromCode(examPaper.getPaperType())) {
            String limitStartTime = examPaperWithQuestionDTO.getLimitDateTime().get(0);
            String limitEndTime = examPaperWithQuestionDTO.getLimitDateTime().get(1);
            // 给 examPaper 的 limitStartTime 属性赋值
            examPaper.setLimitStartTime(DateTimeUtil.parse(limitStartTime, DateTimeUtil.STANDER_FORMAT));
            // 给 examPaper 的 limitEndTime 属性赋值
            examPaper.setLimitEndTime(DateTimeUtil.parse(limitEndTime, DateTimeUtil.STANDER_FORMAT));
        }

    }

    // 将 ExamPaperWithQuestionDTO 中的 titleItems 属性 转换为 JSON 字符串
    public String setExamPaperTextContent(ExamPaperWithQuestionDTO examPaperWithQuestionDTO) {
        AtomicInteger index = new AtomicInteger(1);
        List<ExamPaperTitleItemObject> examPaperTitleItemObjectList = examPaperWithQuestionDTO.getTitleItems()
                .stream()
                .map(examPaperTitleItemDTO -> {
                    ExamPaperTitleItemObject examPaperTitleItemObject = new ExamPaperTitleItemObject();

                    // 给 ExamPaperTitleItemObject 的 name 属性赋值
                    examPaperTitleItemObject.setName(examPaperTitleItemDTO.getName());

                    // 给 ExamPaperTitleItemObject 的 questionItems 属性赋值
                    List<ExamPaperQuestionItemObject> collect = examPaperTitleItemDTO.getQuestionItems()
                            .stream()
                            .map(questionDTO -> {
                                ExamPaperQuestionItemObject  examPaperQuestionItemObject = new ExamPaperQuestionItemObject();
                                examPaperQuestionItemObject.setId(questionDTO.getId());
                                examPaperQuestionItemObject.setItemOrder(index.getAndIncrement());
                                return examPaperQuestionItemObject;
                            })
                            .collect(Collectors.toList());
                    examPaperTitleItemObject.setQuestionItems(collect);

                    return examPaperTitleItemObject;
                }).collect(Collectors.toList());
        return JsonUtil.toJsonStr(examPaperTitleItemObjectList);
    }

    @Override
    public void softDelete(Integer id) {
        ExamPaper examPaper = examPaperMapper.selectByPrimaryKey(id);
        examPaper.setDeleted(true);
        int i = examPaperMapper.updateByPrimaryKeySelective(examPaper);
        if (i <= 0) {
            throw new RuntimeException("删除试卷失败");
        }
    }

    @Override
    public PageInfo<ExamPaperVO> taskExamPage(ExamPaperPageDTO examPaperPageDTO) {

        PageHelper.startPage(examPaperPageDTO.getPageIndex(), examPaperPageDTO.getPageSize(), "id desc");
        List<ExamPaper> examPaperList = examPaperMapper.selectTaskExamByPage(examPaperPageDTO);

        PageInfo<ExamPaper> oldPageInfo = new PageInfo<>(examPaperList);

        // 将List<ExamPaper>转换为List<ExamPaperVO>
        List<ExamPaperVO> examPaperVOList = examPaperList
                .stream()
                .map(new Function<ExamPaper, ExamPaperVO>() {
                    @Override
                    public ExamPaperVO apply(ExamPaper examPaper) {
                        ExamPaperVO examPaperVO = BeanCopyUtils.copyBean(examPaper, ExamPaperVO.class);
                        // BeanUtils 无法将 Date 类型的属性转换为 String 类型，所以需要手动转换
                        examPaperVO.setCreateTime(DateTimeUtil.dateFormat(examPaper.getCreateTime()));
                        return examPaperVO;
                    }
                })
                .collect(Collectors.toList());

        // 将 oldPageInfo 中的所有属性赋值到 PageInfo<ExamPaperVO> 对象，并更改该对象的List属性为 examPaperVOList
        return PageInfoUtil.copyMap(oldPageInfo, examPaperVOList);
    }

    @Override
    public List<FixedPaper> indexFixedPaper(PaperFilter paperFilter) {

        return examPaperMapper.indexFixedPaper(paperFilter);
    }

    @Override
    public List<TimeLimitPaper> indexTimeLimitPaper(PaperFilter paperFilter) {

        return examPaperMapper.indexTimeLimitPaper(paperFilter);
    }

    @Override
    public PageInfo<ExamPaperPageVO> getExamPaperByPageStudent(com.mindskip.xzs.domain.dto.student.exampaper.ExamPaperPageDTO examPaperPageDTO) {

        PageInfo<ExamPaper> oldPageInfo = PageHelper.startPage(examPaperPageDTO.getPageIndex(), examPaperPageDTO.getPageSize(), "id desc")
                .doSelectPageInfo(() -> examPaperMapper.selectByPageStudent(examPaperPageDTO));

        List<ExamPaperPageVO> examPaperPageVOList = oldPageInfo.getList()
                .stream()
                .map(examPaper -> {

                    ExamPaperPageVO examPaperPageVO = BeanCopyUtils.copyBean(examPaper, ExamPaperPageVO.class);

                    examPaperPageVO.setCreateTime(DateTimeUtil.dateFormat(examPaper.getCreateTime()));

                    return examPaperPageVO;
                })
                .collect(Collectors.toList());


        return PageInfoUtil.copyMap(oldPageInfo, examPaperPageVOList);
    }
}
